home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 …ember: Reference Library / Dev.CD Dec 96 RL / Dev.CD Dec 96 RL.toast / Technical Documentation / develop / develop Issue 28 / develop Issue 28 code / MacApp Debugging / TwistDownLists / UTwistDownDocument.cp < prev    next >
Encoding:
Text File  |  1996-09-23  |  76.0 KB  |  2,147 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UTwistDownDocument.cp
  3. // ETO20 MacApp 3.3.1, MPW 3.4.1
  4. // Copyright ©1994-1996 Conrad Kopala
  5. // Twist Down Lists version 2.0a0 7/15/96
  6. //----------------------------------------------------------------------------------------
  7.  
  8. #ifndef __UTWISTDOWNDOCUMENT__
  9. #include "UTwistDownDocument.h"
  10. #endif
  11.  
  12. #ifndef __UPROGRESSINDICATORS__
  13. #include "UProgressIndicators.h"
  14. #endif
  15.  
  16. #ifndef __UTWISTDOWNAPP__
  17. #include "UTwistDownApp.h"
  18. #endif
  19.  
  20. #ifndef __UTWISTDOWNELEMENT__
  21. #include "UTwistDownElement.h"
  22. #endif
  23.  
  24. #ifndef __UTWISTDOWNCONTROL__
  25. #include "UTwistDownControl.h"
  26. #endif
  27.  
  28. #ifndef __UTWISTDOWNVIEW__
  29. #include "UTwistDownView.h"
  30. #endif
  31.  
  32. //MacApp stuff
  33.  
  34. #ifndef __UDEBUG__
  35. #include "UDebug.h"        //PPC
  36. #endif
  37.  
  38. #ifndef __UMACAPPUTILITIES__
  39. #include "UMacAppUtilities.h"
  40. #endif
  41.  
  42. #ifndef __UMENUMGR__
  43. #include "UMenuMgr.h"
  44. #endif
  45.  
  46. #ifndef __UPRINTING__
  47. #include "UPrinting.h"
  48. #endif
  49.  
  50. #ifndef __UVIEWSERVER__
  51. #include "UViewServer.h"
  52. #endif
  53.  
  54. #ifndef __UWINDOW__
  55. #include "UWindow.h"
  56. #endif
  57.  
  58. //ToolBox stuff
  59. #ifndef __ERRORS__
  60. #include "Errors.h"
  61. #endif
  62.  
  63. #ifndef __FILES__
  64. #include "Files.h"
  65. #endif
  66.  
  67. #ifndef __FONTS__    
  68. #include "Fonts.h"
  69. #endif
  70.  
  71. #ifndef __QUICKDRAW__
  72. #include "Quickdraw.h"
  73. #endif
  74.  
  75. #ifndef __AEREGISTRY__
  76. #include "AERegistry.h"
  77. #endif
  78.  
  79. //ANSI stuff
  80. //None
  81. //----------------------------------------------------------------------------------------
  82. // Constants:
  83.  
  84.  
  85. //========================================================================================
  86. // CLASS TTwistDownDocument
  87. //========================================================================================
  88. #undef Inherited
  89. #define Inherited TDocument
  90.  
  91. #pragma segment AOpen
  92. MA_DEFINE_CLASS_M1(TTwistDownDocument, Inherited);
  93.  
  94. //----------------------------------------------------------------------------------------
  95. // TTwistDownDocument constructor 
  96. //----------------------------------------------------------------------------------------
  97. #pragma segment AOpen
  98. TTwistDownDocument::TTwistDownDocument()  
  99. {
  100.  
  101. fVolume = NULL;
  102. fVolumeRefNumber = 0;
  103. fVolumeName = gEmptyString;
  104. fSameVolumeNumber = 0;
  105. fShowInvisibleFiles = FALSE;
  106.  
  107. fDependencies = NULL;
  108.  
  109. fNumberOfDirectoriesToLoad = 0;
  110. fNumberOfFilesToLoad = 0;
  111. fNumberOfItemsToLoad = 0;
  112.  
  113. fNumberOfDirectoriesInList = 0;
  114. fNumberOfFilesInList = 0;
  115. fNumberOfItemsInList = 0;
  116.  
  117. fTwistDownView = NULL;
  118. fHeadOfListElement = NULL;
  119. fTextStyle = gApplicationStyle;
  120.  
  121. fProgressBarIndicator = NULL;
  122. fUpdateAmount = 1;
  123. fProgressUpdateCounter = 0;
  124.  
  125. fSearchMethod = visibleList;
  126.  
  127. #if qDebug
  128. this -> PrintAppConstructorClassInfo();
  129. #endif
  130.  
  131. }
  132. //----------------------------------------------------------------------------------------
  133. // TTwistDownDocument::~TTwistDownDocument    
  134. //----------------------------------------------------------------------------------------
  135. #pragma segment AClose
  136. TTwistDownDocument::~TTwistDownDocument()
  137. {
  138.  
  139.     if (fDependencies)
  140.         fDependencies = (TSimpleDependencySpace*)(FreeIfObject(fDependencies));
  141.  
  142.     this -> FreeData();
  143.     
  144.     fHeadOfListElement = NULL;    //For safety's sake, set it to NULL. It has been freed.
  145.         
  146. #if qDebug
  147. this -> PrintAppDestructorClassInfo();
  148. #endif
  149. }
  150. //----------------------------------------------------------------------------------------
  151. // TTwistDownDocument::ITwistDownDocument: 
  152. //----------------------------------------------------------------------------------------
  153. #pragma segment AOpen
  154. void TTwistDownDocument::ITwistDownDocument(TVolume* itsVolume, Boolean showInvisibleFiles)
  155. {
  156.     this -> IDocument();    //IDocument contains a failure handler so any failure there will
  157.                                                 //get us out of ITwistDownDocument. 
  158.     
  159.     FailInfo fi;
  160.     Try(fi)
  161.     {
  162.  
  163.         fReopenAlert = TRUE;
  164.  
  165.         fDependencies = new TSimpleDependencySpace;    //Used for updating the progress indicator.
  166.         fDependencies -> ISimpleDependencySpace();
  167.         
  168.         fVolume = itsVolume;
  169.         CStr31 itsName;
  170.         itsVolume -> GetName(itsName);
  171.         this -> SetVolumeData(itsVolume -> GetVolRefNum(), itsName);    //This is the most likely
  172.                                                                                                                                     //source of a failure.
  173.  
  174.         fShowInvisibleFiles = showInvisibleFiles;
  175.     
  176.         fi.Success();
  177.     }
  178.     else // Recover
  179.     {
  180.         this->Free();
  181.         fi.ReSignal();                
  182.     }
  183.  
  184. }
  185. //----------------------------------------------------------------------------------------
  186. // TTwistDownDocument::CloseAndFree: 
  187. //----------------------------------------------------------------------------------------
  188. #pragma segment AClose
  189. void  TTwistDownDocument::CloseAndFree()
  190. {
  191.     if (fTwistDownView)
  192.         {
  193.             TWindow* theWindow = NULL;
  194.             theWindow = fTwistDownView -> GetWindow();
  195.             if (theWindow)
  196.                 gTwistDownApp -> RemoveWindowFromWindowsMenuList(theWindow);
  197.         }
  198.         
  199.     Inherited::CloseAndFree();
  200. }
  201. //----------------------------------------------------------------------------------------
  202. // TTwistDownDocument::GetDependencySpace: 
  203. //----------------------------------------------------------------------------------------
  204. #pragma segment AOpen
  205. TDependencySpace* TTwistDownDocument::GetDependencySpace()
  206. {
  207.     return fDependencies;
  208. }
  209. //----------------------------------------------------------------------------------------
  210. // TTwistDownDocument::Changed: 
  211. //----------------------------------------------------------------------------------------
  212. #pragma segment AReadFile
  213. void TTwistDownDocument::Changed(ChangeID theChange, TObject* changedBy)
  214. {
  215. //The following code is from TObject::Changed. I want to avoid the TDocument::Changed method
  216. //because it sets fChangeCount to something other than zero which causes the application to
  217. //ask the user about saving the document when it is closed and TwistDownLists does not save
  218. //documents. I also wanted to experiment with dependencies.
  219.  
  220.     TDependencySpace* itsDependencySpace = this -> GetDependencySpace();
  221.     if (itsDependencySpace)
  222.         itsDependencySpace -> NotifierChanged(this, theChange, changedBy);
  223. }
  224.  
  225. //----------------------------------------------------------------------------------------
  226. // TTwistDownDocument::FindDocument: analog of TFileBasedDocument::FindDocument    
  227. //----------------------------------------------------------------------------------------
  228. #pragma segment ARes
  229.  
  230. Boolean TTwistDownDocument::FindDocument(TVolume* aVolume)
  231. {
  232.     return fVolume -> IsSameVolume(aVolume);
  233. }
  234. //----------------------------------------------------------------------------------------
  235. // TTwistDownDocument::SetVolumeData: used by ITwistDownDocument    
  236. //----------------------------------------------------------------------------------------
  237. #pragma segment AOpen
  238. void TTwistDownDocument::SetVolumeData(short volumeRefNumber, CStr31 volumeName)
  239. {
  240.  
  241.     FailInfo fi;
  242.     Try(fi)
  243.         {
  244.             MAVolatile(HVolumeParam,    pb);
  245.  
  246.             fVolumeRefNumber = volumeRefNumber;
  247.             fVolumeName = volumeName;
  248.  
  249.             fSameVolumeNumber = gTwistDownApp -> GetNextDocumentNumber(volumeName);
  250.  
  251.             if (fSameVolumeNumber == 1)
  252.                 fTitle = volumeName;
  253.             else
  254.                 {
  255.                     CStr255 docNum;
  256.                     NumToString(fSameVolumeNumber, docNum);
  257.                     fTitle = volumeName;
  258.                     fTitle += " ";
  259.                     fTitle += docNum;
  260.                 }
  261.     
  262.             BlockSet((Ptr) & pb, sizeof(HVolumeParam), 0x00);    //For debugging fun  and games, comment
  263.                                                                                                                 //this statement out. You will discover
  264.                                                                                                                 //why parameter blocks should always be 
  265.                                                                                                                 //cleared before using them.
  266.  
  267.             pb.ioVRefNum = fVolumeRefNumber;
  268.             pb.ioVolIndex = 0;
  269.  
  270.             FailOSErr(PBHGetVInfoSync((HParmBlkPtr)&pb));
  271.             
  272.             fNumberOfDirectoriesToLoad = pb.ioVDirCnt;    
  273.             fNumberOfFilesToLoad = pb.ioVFilCnt;
  274.             fNumberOfItemsToLoad = fNumberOfDirectoriesToLoad + fNumberOfFilesToLoad;
  275.                     
  276.             long spaceRequiredForElements = fNumberOfItemsToLoad*(gTwistDownApp -> fTDElementClassSize);
  277.             long spaceRequiredForControls = fNumberOfDirectoriesToLoad*(gTwistDownApp -> fTDControlClassSize);            
  278.  
  279.             if (!HaveObjectHeapSpace(spaceRequiredForElements + spaceRequiredForControls +3*1024))
  280.                 Failure(memFullErr, 0);
  281.  
  282.         fi.Success();
  283.     }
  284. else // Recover
  285.     {
  286.         fi.ReSignal();                
  287.     }
  288.  
  289. }
  290. //----------------------------------------------------------------------------------------
  291. // TTwistDownDocument::SetUpdateAmount    
  292. //----------------------------------------------------------------------------------------
  293. #pragma segment AOpen
  294. void TTwistDownDocument::SetUpdateAmountTo(long updateAmount)
  295. {
  296. fUpdateAmount = updateAmount;
  297.  
  298. if (fProgressBarIndicator)
  299.     fProgressBarIndicator -> SetUpdateAmountTo(fUpdateAmount);
  300. }
  301. //----------------------------------------------------------------------------------------
  302. // TTwistDownDocument::FreeData: 
  303. //----------------------------------------------------------------------------------------
  304. #pragma segment ARes
  305. void TTwistDownDocument::FreeData()
  306. {
  307. fVolume = (TVolume*)(FreeIfObject(fVolume));                                        
  308. fVolumeName = gEmptyString;
  309.  
  310. if (fHeadOfListElement != NULL)
  311.     this -> FreeTwistDownList(fHeadOfListElement);
  312. }
  313. //----------------------------------------------------------------------------------------
  314. // TTwistDownDocument::FreeTwistDownList: 
  315. //----------------------------------------------------------------------------------------
  316. #pragma segment AClose
  317. void TTwistDownDocument::FreeTwistDownList(TTwistDownElement* twistDownElement)
  318. {
  319. TTwistDownElement* successorElement;
  320. TTwistDownElement* descendantElement;
  321.  
  322. while (twistDownElement != NULL) 
  323.     {
  324.         
  325.         successorElement = twistDownElement -> GetSuccessorElement();
  326.         descendantElement = twistDownElement -> GetDescendantElement();
  327.         
  328.         //Note: When the TTwistDownView is closed, the first thing it does is free all 
  329.         //the TTwistDownControls. The controls are freed before FreeTwistDownList is called.
  330.         //The TTwistDownControl::Free() method sets the fTwistDownControl field of
  331.         //the twistDownElement to NULL. Therefore, controls are not freed here.
  332.         
  333.         if (twistDownElement)
  334.             this -> DecrementItemsInList();
  335.             
  336.         twistDownElement = (TTwistDownElement*)FreeIfObject(twistDownElement);
  337.     
  338.         if (descendantElement != NULL)
  339.             this -> FreeTwistDownList(descendantElement);
  340.         
  341.         twistDownElement = successorElement;
  342.     }
  343. }
  344. //----------------------------------------------------------------------------------------
  345. // TTwistDownDocument::DoMakeViews: 
  346. //----------------------------------------------------------------------------------------
  347. #pragma segment AOpen
  348. void TTwistDownDocument::DoMakeViews(Boolean forPrinting)
  349. {
  350.  
  351. TWindow* aTwistDownWindow = NULL;    
  352. TTwistDownView* aTwistDownView = NULL;
  353.  
  354. FailInfo fi;
  355. Try(fi)
  356. {
  357.     if (!forPrinting)
  358.         {
  359.             FailNIL(aTwistDownWindow = gViewServer -> NewTemplateWindow(kTwistDownWindowID, this));    
  360.             
  361.             if (aTwistDownWindow != NULL)
  362.                 {
  363.                     aTwistDownView = (TTwistDownView*) (aTwistDownWindow -> FindSubView(kTwistDownViewID));
  364.                     fTwistDownView = aTwistDownView;
  365.     
  366.                     this -> AddPrintHandlerToView(fTwistDownView);
  367.  
  368.                     gTwistDownApp -> AddWindowToWindowsMenuList(aTwistDownWindow);
  369.                 }
  370.  
  371.         }
  372. #if qDebug        
  373.     else    //forPrinting    -Should never get here
  374.         ProgramBreak("ProgramBreak -DoMakeViews forPrinting = TRUE.");
  375. #endif
  376.         
  377.     fi.Success();
  378. }
  379. else // Recover
  380. {
  381.     fi.ReSignal();
  382. }        
  383.         
  384. }
  385. //----------------------------------------------------------------------------------------
  386. // TTwistDownDocument::AddPrintHandlerToView: 
  387. //----------------------------------------------------------------------------------------
  388. #pragma segment AOpen
  389. void TTwistDownDocument::AddPrintHandlerToView(TView* aView)
  390. {
  391.  
  392.     TPrintHandler* aPrintHandler = (TPrintHandler*)gPrintHandler -> Clone();
  393.  
  394.     aPrintHandler -> fView = aView;
  395.     aPrintHandler -> SetDefaultPrintInfo();
  396.     this -> AttachPrintHandler(aPrintHandler);
  397.     if (aView)
  398.         aView -> AttachPrintHandler(aPrintHandler);
  399.  
  400. //    TStdPrintHandler* printHandler = new TStdPrintHandler;
  401. //    printHandler -> IStdPrintHandler(this, aView, !kSquareDots, !kFixedSize, !kFixedSize);
  402. }
  403. //----------------------------------------------------------------------------------------
  404. // TTwistDownDocument::DoSetupMenus: 
  405. //----------------------------------------------------------------------------------------
  406. #pragma segment ARes
  407. void TTwistDownDocument::DoSetupMenus()
  408. {
  409.         
  410.     Inherited::DoSetupMenus();
  411.     
  412.     Enable(cSaveAs, FALSE);
  413.     Enable(cSaveCopy, FALSE);
  414.     Enable(cSave, FALSE);
  415.     Enable(cRevert, FALSE);
  416.     
  417. }
  418. //----------------------------------------------------------------------------------------
  419. // TTwistDownDocument::ReadDocument: 
  420. //----------------------------------------------------------------------------------------
  421. #pragma segment AReadFile
  422. void TTwistDownDocument::ReadDocument(Boolean forPrinting)
  423. {
  424. #pragma unused forPrinting
  425. MAVolatileInit(OSErr, savedError, 0);
  426. MAVolatileInit(long, savedMessage, 0);
  427.     
  428. //myOSErr is passed by reference. It is used to signal an out of memory condition when loading the list.
  429. OSErr myOSErr = noErr;
  430.  
  431. MAVolatileInit(long, volumeDirIndex, fsRtDirID);    //Must this be volatile?
  432. MAVolatileInit(short, indentLevel, 0);    //Must this be volatile?
  433.  
  434. CStr255 itsOperationString;
  435. GetIndString(itsOperationString, kProgressIndicatorOperationStrings, 3);
  436.  
  437. CStr255 itsSubjectString = fVolumeName;
  438. fProgressBarIndicator = NewProgressBarIndicator(itsOperationString, itsSubjectString);
  439.  
  440. this -> AddDependent(fProgressBarIndicator);
  441. fProgressBarIndicator -> PrepareToStart(TRUE);
  442.  
  443. long barLength = fProgressBarIndicator -> GetBarLength();
  444.  
  445. //The default value for fUpdateAmount is set to 1.                                
  446. //Unfortunately, if there are a lot of items to read and the progress bar is updated each time 
  447. //an item is read, it takes a long time to populate the list. With the following if statement,
  448. //the update amount is adjusted so that the progress bar is updated only when enough
  449. //progress has been made to update it by at least one pixel. This noticibly speeds things up. 
  450. //Comment out the following if statement and see for yourself. 
  451.  
  452. if (fNumberOfItemsToLoad > barLength)
  453.     {
  454.         long updateAmount = fNumberOfItemsToLoad/barLength;    
  455.         this -> SetUpdateAmountTo(updateAmount);    
  456.     }
  457.  
  458. fProgressBarIndicator -> Start(fNumberOfItemsToLoad);
  459.  
  460.     FailInfo fi;
  461.     Try(fi)
  462.     {
  463.  
  464.         fHeadOfListElement = this -> BuildTwistDownList(indentLevel, volumeDirIndex, myOSErr);
  465.         
  466.         if (myOSErr != noErr)
  467.             Failure(myOSErr, 0);
  468.             
  469.         fNumberOfFilesInList = fNumberOfItemsInList - fNumberOfDirectoriesInList;
  470.             
  471.         fi.Success();                                                
  472.     }
  473.     else
  474.     {
  475.     //Save the error info until after we've gotten rid of the progress indicator.
  476.     //Then we can signal Failure.
  477.         savedError = fi.error;
  478.         savedMessage = fi.message;
  479.         if (!savedMessage)
  480.             savedMessage = messageOpenFailed;
  481.  
  482.     }
  483.     
  484. if (fProgressBarIndicator != NULL)
  485.     {
  486.         fProgressBarIndicator -> Stop();
  487.         this -> RemoveDependent(fProgressBarIndicator);
  488.         fProgressBarIndicator = (TProgressBarIndicator*)FreeIfObject(fProgressBarIndicator);
  489.     }    
  490.  
  491. if (savedError != noErr)
  492.     Failure(savedError, savedMessage);
  493.  
  494. }
  495. //----------------------------------------------------------------------------------------
  496. // TTwistDownDocument::DoPostMakeViews: 
  497. //----------------------------------------------------------------------------------------
  498. #pragma segment AOpen
  499. void TTwistDownDocument::DoPostMakeViews(Boolean forPrinting)
  500. {
  501. Inherited::DoPostMakeViews(forPrinting);
  502.  
  503. TWindow* aTwistDownWindow = NULL;    
  504. aTwistDownWindow = fTwistDownView -> GetWindow();
  505. gTwistDownApp -> AddWindowToWindowsMenuList(aTwistDownWindow);
  506. }
  507. //----------------------------------------------------------------------------------------
  508. // TTwistDownDocument::BuildTwistDownList:    
  509. //----------------------------------------------------------------------------------------
  510. #pragma segment AReadFile
  511. TTwistDownElement* TTwistDownDocument::BuildTwistDownList(short indentLevel,
  512.                                                 long volumeDirIndex, OSErr& myOSErr)
  513. {
  514.  
  515. HFileInfo pb;
  516. CStr63 fileName = gEmptyString;
  517. FInfo theFinderInfo;
  518.         
  519. OSErr    status = noErr;            //status is set by PBGetCatInfoSync and signals no more files, i.e. we're done.
  520.  
  521. short dirIndex;
  522. TTwistDownElement* previousElement;
  523. TTwistDownElement* firstElement;
  524. TTwistDownElement* thisElement;
  525.  
  526. BlockSet((Ptr) & pb, sizeof(HFileInfo), 0x00);// zero-out our storage 
  527.  
  528. pb.ioNamePtr = fileName;    //Note that pb.ioNamePtr is a pointer to fileName.
  529. pb.ioVRefNum = fVolumeRefNumber;
  530. dirIndex = 1;
  531.  
  532. previousElement = NULL;
  533. firstElement = NULL;
  534. thisElement = NULL;
  535.  
  536. Boolean isVisible = FALSE;
  537. Boolean showIt = FALSE;
  538.  
  539. //The do-while loop scans the volume for all directories and files. It exits when 
  540. //    status == someError, most likely fnfErr (-43),
  541. //    myOSErr == someError, most likely memFullErr (-108), or
  542. //    fProgressBarIndicator -> IsStopped() == TRUE
  543. //
  544. //The status == fnfErr means the current loop is at the end of a chain in the hierarchy.
  545. //The myOSErr == memFullErr means we ran out of memory when MakeTwistDownElement attempted
  546. //to make a new twistDownElement.
  547. //The fProgressBarIndicator -> IsStopped() == TRUE condition means the user clicked on the
  548. //stop button in the progress indicator thus causing the loop to terminate early.
  549.  
  550. do 
  551. {
  552.  
  553. status = noErr;                            //Not absolutely necessary, cleared for debugging purposes.
  554. fileName = gEmptyString;        //Not absolutely necessary, cleared for debugging purposes.
  555. pb.ioFDirIndex = dirIndex;
  556. pb.ioDirID = volumeDirIndex;    //which happens to = fsRtDirID  root directory = 2
  557. status = PBGetCatInfoSync((CInfoPBPtr) &pb);
  558.  
  559. if (status == noErr)
  560.     {
  561.         if (fProgressBarIndicator != NULL)
  562.             {
  563.                 ++fProgressUpdateCounter;
  564.                 if (fProgressUpdateCounter >= fUpdateAmount)
  565.                     {
  566.                         fProgressUpdateCounter = 0;
  567.                         this -> Changed(mUpdateProgressBar, this);
  568.                     }
  569.             }
  570.  
  571.         isVisible = TRUE;    //Assume the item is visible.            
  572.         theFinderInfo = pb.ioFlFndrInfo;    
  573.         if ((theFinderInfo.fdFlags & kIsInvisible) == kIsInvisible)
  574.                 isVisible = FALSE;
  575.     
  576.         showIt = FALSE;        //Assume showIt is FALSE
  577.         if (fShowInvisibleFiles == TRUE || isVisible == TRUE)
  578.             showIt = TRUE;
  579.  
  580.         if (showIt == TRUE)
  581.             thisElement = this -> MakeTwistDownElement(previousElement,indentLevel,fileName,myOSErr);    
  582.                 
  583.         if (myOSErr == noErr) 
  584.             {
  585.                 if (firstElement == NULL)
  586.                     firstElement = thisElement;
  587.             
  588. //If thisElement is a folder and it is visible, descend the hierarchy by calling ourselves recursively. 
  589. //Store the first element in the new sub-list into thisElement's fDescendantElement. 
  590. //Note that thisElement's fHasSubList will be TRUE even if thisElement has no descendants 
  591. //(ie. nothing in the folder).
  592.  
  593.                 if ((pb.ioFlAttrib & ioDirMask) == ioDirMask && thisElement != NULL && showIt == TRUE) 
  594.                     {    
  595.                         thisElement -> SetHasSubListFlag();
  596.                         fNumberOfDirectoriesInList++;
  597.                         thisElement -> SetDescendantElementTo(this -> BuildTwistDownList(indentLevel + 1,pb.ioDirID, myOSErr));
  598.                     }
  599.                 ++dirIndex;
  600.                  previousElement = thisElement;    /* Set linkage for next file    */
  601.  
  602.             }    //end if (myOSErr == noErr) 
  603.     }    //end if (status == noErr)
  604.     
  605. while (status == noErr && myOSErr == noErr && fProgressBarIndicator -> IsStopped() == FALSE);
  606.     
  607. return (firstElement);
  608.  
  609. }
  610. //----------------------------------------------------------------------------------------
  611. // TTwistDownDocument::MakeTwistDownElement: 
  612. //----------------------------------------------------------------------------------------
  613. #pragma segment AReadFile
  614. TTwistDownElement* TTwistDownDocument::MakeTwistDownElement(TTwistDownElement* previousElement,
  615.                                                                                 short indentLevel,CStr63 displayedText, OSErr& myOSErr)
  616. {
  617.  
  618. TTwistDownElement* theNewElement = NULL;
  619.  
  620. FailInfo fi;
  621. Try(fi)
  622. {
  623.  
  624.     FailNIL(theNewElement = new TTwistDownElement);
  625.     theNewElement -> ITwistDownElement(this, indentLevel, displayedText);
  626.  
  627. /*    
  628.     //The FailHere test is commented out because it is being used in TTwistDownView::NewTwistDownControl
  629.     //to test failure handling there when opening a disk. Probably need a second fail here flag.
  630.     
  631.     //Note: To properly use the FailHere type test, always initialize the object whose failure 
  632.     //you're simulating before signalling Failure(errFailHere, 0);. If you don't the failure recovery
  633.     //won't work when it attempts to free the object.    
  634.     if (gFailHere)
  635.         {
  636.             CStr63 failHereText = "FailHere";
  637.             if (failHereText == displayedText)
  638.                 Failure(errFailHere, 0);
  639.         }    
  640. */
  641.  
  642.     this -> IncrementItemsInList();
  643.     theNewElement -> SetItemInList(fNumberOfItemsInList);                
  644.         
  645.     if (previousElement != NULL)
  646.         previousElement -> SetSuccessorElementTo(theNewElement);    
  647.         
  648.     fi.Success();
  649. }
  650.     // Recover. Do not ReSignal. If you do, the program will jump over any intervening 
  651.     // instances of BuildTwistDownList up to ReadDocument. As a consequence 
  652.     // fHeadOfListElement will be NULL and all the elements that were created by
  653.     // BuildTwistDownList will not be freed. Result = a memory leak like you've
  654.     // never seen before. Try it and see for yourself.
  655.                         
  656. else 
  657. {
  658.     theNewElement = (TTwistDownElement*)(FreeIfObject(theNewElement));
  659.     myOSErr = fi.error;
  660. }        
  661.  
  662. return theNewElement;
  663.  
  664. }
  665. //----------------------------------------------------------------------------------------
  666. // TTwistDownDocument::DisposeTwistDownElement: 
  667. //----------------------------------------------------------------------------------------
  668. #pragma segment AClose
  669. void TTwistDownDocument::DisposeTwistDownElement(TTwistDownElement* twistDownElement)
  670. {
  671. TTwistDownElement* successorElement;
  672. TTwistDownElement* descendantElement;
  673.         
  674. while (twistDownElement != NULL) 
  675. {
  676.     successorElement = twistDownElement -> GetSuccessorElement();
  677.     descendantElement = twistDownElement -> GetDescendantElement();
  678.     TTwistDownControl* twistDownControl = twistDownElement -> GetTwistDownControl();
  679.     if (twistDownControl != NULL)
  680.         {
  681.             fTwistDownView -> RemoveSubView(twistDownControl);
  682.             twistDownControl = (TTwistDownControl*)FreeIfObject(twistDownControl);
  683.             
  684.             //Note: The TTwistDownControl::Free() method sets the fTwistDownControl field of
  685.             //the twistDownElement to NULL;            
  686.  
  687.         }
  688.         
  689.     twistDownElement = (TTwistDownElement*)FreeIfObject(twistDownElement);
  690.     
  691.     if (descendantElement != NULL)
  692.         DisposeTwistDownElement(descendantElement);
  693.         
  694.     twistDownElement = successorElement;
  695.     }
  696. }
  697. //----------------------------------------------------------------------------------------
  698. // TTwistDownDocument::CountVisibleElements: 
  699. //----------------------------------------------------------------------------------------
  700. #pragma segment ARes
  701. long TTwistDownDocument::CountVisibleElements(TTwistDownElement* twistDownElement)
  702. {
  703. long result = 0;
  704.  
  705. while (twistDownElement != NULL) 
  706.     {
  707.         ++result;
  708.         if (twistDownElement -> TestShowSubListFlag())
  709.             result += this -> CountVisibleElements(twistDownElement -> GetDescendantElement());
  710.             
  711.         twistDownElement = twistDownElement -> GetSuccessorElement();
  712.     }    
  713.     
  714. return result;
  715.  
  716. }
  717. //----------------------------------------------------------------------------------------
  718. // TTwistDownDocument::GetTwistDownElementAt: 
  719. //----------------------------------------------------------------------------------------
  720. #pragma segment ARes
  721. void TTwistDownDocument::GetTwistDownElementAt(short anItem, TTwistDownElement* startingTwistDownElement, 
  722.                                                             TTwistDownElement** currentTwistDownElement, short &rowNumber)
  723. {
  724. MAVolatileInit(TTwistDownElement*, twistDownElement, NULL);
  725.  
  726. twistDownElement = startingTwistDownElement;
  727.  
  728. while (twistDownElement != NULL && rowNumber != anItem) 
  729.     {
  730.         ++rowNumber;
  731.         *currentTwistDownElement = twistDownElement;
  732.             
  733.         if (twistDownElement -> TestShowSubListFlag())
  734.             {
  735.                 this -> GetTwistDownElementAt(anItem, twistDownElement -> GetDescendantElement(), 
  736.                                                                             currentTwistDownElement, rowNumber);
  737.         
  738.             }
  739.         twistDownElement = twistDownElement -> GetSuccessorElement();
  740.     }    
  741.  
  742. }
  743. //----------------------------------------------------------------------------------------
  744. // TTwistDownDocument::GetTwistDownElementRowNumber: 
  745. //----------------------------------------------------------------------------------------
  746. #pragma segment ARes
  747. void TTwistDownDocument::GetTwistDownElementRowNumber(TTwistDownElement* startingTwistDownElement, 
  748.                                                             TTwistDownElement* targetTwistDownElement,
  749.                                                             TTwistDownElement** currentTwistDownElement, short &rowNumber)
  750. {
  751. MAVolatileInit(TTwistDownElement*, twistDownElement, NULL);
  752.  
  753. twistDownElement = startingTwistDownElement;
  754.  
  755. while (twistDownElement != NULL && *currentTwistDownElement != targetTwistDownElement) 
  756.     {
  757.         ++rowNumber;
  758.         *currentTwistDownElement = twistDownElement;
  759.             
  760.         if (twistDownElement -> TestShowSubListFlag())
  761.             {
  762.                 this -> GetTwistDownElementRowNumber(twistDownElement -> GetDescendantElement(), targetTwistDownElement,
  763.                                                                             currentTwistDownElement, rowNumber);
  764.         
  765.             }
  766.         twistDownElement = twistDownElement -> GetSuccessorElement();
  767.     }    
  768.  
  769. }
  770. //----------------------------------------------------------------------------------------
  771. // TTwistDownDocument::GetHeadOfList: 
  772. //----------------------------------------------------------------------------------------
  773. #pragma segment ARes
  774. TTwistDownElement* TTwistDownDocument::GetHeadOfList()
  775. {
  776. return fHeadOfListElement;
  777. }
  778. //----------------------------------------------------------------------------------------
  779. // TTwistDownDocument::ExpandElement: 
  780. //----------------------------------------------------------------------------------------
  781. #pragma segment ARes
  782. void TTwistDownDocument::ExpandElement(TTwistDownElement* twistDownElementToExpand)
  783. {
  784. OSErr myOSErr = noErr; //passed by reference to AddTwistDownControls.
  785. TTwistDownElement* currentTwistDownElement = NULL;
  786. short targetRowNumber = 0;
  787. short rowNumber = 0;
  788.  
  789. rowNumber = 0;
  790. this -> GetTwistDownElementRowNumber(fHeadOfListElement, twistDownElementToExpand, 
  791.                                                                                                         ¤tTwistDownElement, rowNumber);
  792.  
  793. targetRowNumber = rowNumber + 1;    //I want to insert rows in front of the row following the twistDownElementToExpand.
  794.                                                                     //targetRowNumber may 'point' to a row that doesn't exist. For example, the row
  795.                                                                     //following the last twistDownElement. I let BuildVisibleList take care of 
  796.                                                                     //this situation.
  797.                                                         
  798. twistDownElementToExpand -> SetShowSubListFlag();
  799.  
  800. FailInfo fi;
  801. Try(fi)
  802.     {
  803.         rowNumber = 0;
  804.         fTwistDownView -> AddTwistDownControls(fHeadOfListElement, rowNumber, myOSErr);    //This puts in the new controls 
  805.                                                                                                                                                                         //with the proper locations.
  806.  
  807.         if (myOSErr != noErr)
  808.             Failure(myOSErr, 0);
  809.                     
  810.         rowNumber = 0;
  811.         fTwistDownView -> UpdateTwistDownControlLocations(fHeadOfListElement, rowNumber); //This updates the locations 
  812.                                                                                                                                                                             //of all the controls.
  813.                                                                                                                                 
  814.         myOSErr = fTwistDownView -> BuildVisibleList(targetRowNumber);    //Inserts rows as required in front of 
  815.                                                                                                                                         //targetRowNumber unless it is beyond the end 
  816.                                                                                                                                         //of the currently displayed list. In that
  817.                                                                                                                                         //case, the rows are inserted last.
  818.  
  819.         //Ordinarily, I would test myOSErr to make sure we hadn't failed because we attempted to add
  820.         //too many rows to TTwistDownView. However, we always call TTwistDownElement::CouldExpandElement()
  821.         //in either TTwistDownControl::DoMouseUp or TTwistDownElement::DoScriptCommand and if too many
  822.         //rows would be added, we fail there rather than letting the operation get this far. The only
  823.         //failure that can occur in this method is an out of memory condition while adding new TTwistDownControls.
  824.         //if (myOSErr == errTooManyRows)
  825.         //    Failure(errTooManyRows, msgTooManyRows);
  826.         
  827.         fTwistDownView -> ResizeTwistDownViewRows();    //Adjusts the size of the view to accomodate the exact number of rows.
  828.         fi.Success();
  829.     }
  830. else
  831.     {
  832.         twistDownElementToExpand -> ClearShowSubListFlag();
  833.         TTwistDownElement* descendantTwistDownElement = twistDownElementToExpand -> GetDescendantElement();
  834.         fTwistDownView -> DeleteTwistDownControls(descendantTwistDownElement);
  835.         fi.ReSignal();
  836.     }
  837. }    //TTwistDownDocument::ExpandElement
  838. //----------------------------------------------------------------------------------------
  839. // TTwistDownDocument::CollapseElement: 
  840. //----------------------------------------------------------------------------------------
  841. #pragma segment ARes
  842. void TTwistDownDocument::CollapseElement(TTwistDownElement* twistDownElementToCollapse)
  843. {
  844. OSErr myOSErr = noErr;
  845. TTwistDownElement* descendantTwistDownElement = NULL;
  846. TTwistDownElement* currentTwistDownElement = NULL;
  847. short targetRowNumber = 0;
  848. short rowNumber = 0;
  849.  
  850. rowNumber = 0;
  851. this -> GetTwistDownElementRowNumber(fHeadOfListElement, twistDownElementToCollapse, 
  852.                                                                                                             ¤tTwistDownElement, rowNumber);
  853. targetRowNumber = rowNumber + 1;
  854.  
  855. descendantTwistDownElement = twistDownElementToCollapse -> GetDescendantElement();
  856. fTwistDownView -> DeleteTwistDownControls(descendantTwistDownElement);
  857.     
  858. twistDownElementToCollapse -> ClearShowSubListFlag();
  859.  
  860. rowNumber = 0;
  861. fTwistDownView -> UpdateTwistDownControlLocations(fHeadOfListElement, rowNumber);
  862.  
  863. myOSErr = fTwistDownView -> BuildVisibleList(targetRowNumber);     //myOSErr isn't tested because
  864.                                                                                                                                 //a tooManyRows error should
  865.                                                                                                                                 //have been caught before we
  866.                                                                                                                                 //ever get here.
  867. fTwistDownView -> ResizeTwistDownViewRows();
  868.  
  869. }    //TTwistDownDocument::CollapseElement: 
  870. //----------------------------------------------------------------------------------------
  871. // TTwistDownDocument::SetShowSubListFlags: Used by ExpandAll    
  872. //----------------------------------------------------------------------------------------
  873. #pragma segment ARes
  874. //When the Expand All command is executed, all fShowSubList flags of all twistDownElements
  875. //are set to TRUE.
  876. void TTwistDownDocument::SetShowSubListFlags(TTwistDownElement* twistDownElement)
  877. {
  878.     while (twistDownElement != NULL) 
  879.         {
  880.             if (twistDownElement -> TestHasSubListFlag())    //Only select those twistDownElements
  881.                                                                                                         //that have a sublist (have a descendant element)
  882.                 {
  883.                     twistDownElement -> SetShowSubListFlag();    //This sets fOldShowSubList to the current
  884.                                                                                                         //value of fShowSubList and then sets
  885.                                                                                                         //fShowSubList to TRUE.
  886.                                                                                                         
  887.                     this -> SetShowSubListFlags(twistDownElement -> GetDescendantElement());
  888.                 }
  889.                 
  890.             twistDownElement = twistDownElement -> GetSuccessorElement();
  891.         }    
  892. }
  893. //----------------------------------------------------------------------------------------
  894. // TTwistDownDocument::ClearShowSubListFlags: Used by CollapseAll    
  895. //----------------------------------------------------------------------------------------
  896. #pragma segment ARes
  897. //When the Collapse All command is executed, the fShowSubList flag of all twistDownElements
  898. //is set to FALSE. At present, fOldShowSublist is set to the current value of fShowSubList
  899. //before fShowSubList is set to FALSE. I probably should set fOldShowSubList to FALSE.
  900.  
  901. void TTwistDownDocument::ClearShowSubListFlags(TTwistDownElement* twistDownElement)
  902. {
  903.     while (twistDownElement != NULL) 
  904.         {
  905.             if (twistDownElement -> TestHasSubListFlag())    //Only select those twistDownElements
  906.                                                                                                         //that have a sublist (have a descendant element)
  907.                 {
  908.                     twistDownElement -> ClearShowSubListFlag();    
  909.                     this -> ClearShowSubListFlags(twistDownElement -> GetDescendantElement());
  910.                 }
  911.                 
  912.             twistDownElement = twistDownElement -> GetSuccessorElement();
  913.         }    
  914. }
  915. //----------------------------------------------------------------------------------------
  916. // TTwistDownDocument::RestoreShowSubListFlags: Used to recover from a failed ExpandAll    
  917. //----------------------------------------------------------------------------------------
  918. #pragma segment ARes
  919. //If the execution of ExpandAll should fail (out of memory), we must recover. To do that
  920. //we must restore the value of fShowSubList to its previous value. This method restores
  921. // fShowSubList to the value of fOldShowSublist and then sets fOldShowSubList to FALSE.
  922.  
  923. void TTwistDownDocument::RestoreShowSubListFlags(TTwistDownElement* twistDownElement)
  924. {
  925.     while (twistDownElement != NULL) 
  926.         {
  927.             if (twistDownElement -> TestHasSubListFlag())
  928.                 {
  929.                     twistDownElement -> RestoreShowSubListFlag();    
  930.                     this -> RestoreShowSubListFlags(twistDownElement -> GetDescendantElement());
  931.                 }
  932.                 
  933.             twistDownElement = twistDownElement -> GetSuccessorElement();
  934.         }    
  935. }
  936. //----------------------------------------------------------------------------------------
  937. // TTwistDownDocument::CollapseAll: used by TCollapseAllCommand::DoIt    
  938. //----------------------------------------------------------------------------------------
  939. #pragma segment ARes
  940. //Note:
  941. void TTwistDownDocument::CollapseAll()
  942. {
  943. OSErr myOSErr = noErr;
  944. short rowNumber = 0;
  945.  
  946. fTwistDownView -> DeleteTwistDownControls(fHeadOfListElement);    //First delete existing controls unless
  947.                                                                                                                                 //twistDownElement -> fIndentLevel == 0.
  948.                                                                                                                                 //
  949.  
  950. this -> ClearShowSubListFlags(fHeadOfListElement);        //The controls must be deleted before the
  951.                                                                                                             //fShowSubList flags are cleared. If the
  952.                                                                                                             //flags are cleared first, DeleteTwistDownControls
  953.                                                                                                             //will not traverse the list because it uses
  954.                                                                                                             //fShowSubList to descend the hierarchy.
  955.                                                                                                             //Consequently, controls will not be deleted.
  956.  
  957. rowNumber = 0;
  958. fTwistDownView -> UpdateTwistDownControlLocations(fHeadOfListElement, rowNumber);
  959.  
  960. rowNumber = 1;
  961. myOSErr = fTwistDownView -> BuildVisibleList(rowNumber);
  962.  
  963. fTwistDownView -> ResizeTwistDownViewRows();
  964.  
  965. }    //TTwistDownDocument::CollapseAll
  966. //----------------------------------------------------------------------------------------
  967. // TTwistDownDocument::InstallTextStyle: 
  968. //----------------------------------------------------------------------------------------
  969. #pragma segment ADoCommand
  970. void TTwistDownDocument::InstallTextStyle(const TextStyle& itsTextStyle)
  971. {
  972. fTextStyle = itsTextStyle;
  973. }
  974. //----------------------------------------------------------------------------------------
  975. // TTwistDownDocument::UpdateTwistDownElements: called by TTwistDownView::DoChangeWritingDirection
  976. //                                                                                                                TTwistDownView::DoChangeTextStyle
  977. //----------------------------------------------------------------------------------------
  978. #pragma segment ARes
  979. void TTwistDownDocument::UpdateTwistDownElements(TTwistDownElement* twistDownElement, short &rowNumber)
  980. {
  981.  
  982. while (twistDownElement != NULL) 
  983.     {
  984.         ++rowNumber;
  985.         TTwistDownControl* twistDownControl = twistDownElement -> GetTwistDownControl();
  986.         if (twistDownControl != NULL)
  987.             {
  988.                 twistDownControl -> InstallTextStyle(fTextStyle, kDontRedraw);    //In another time and place it
  989.                                                                                                                                                 //might be necessary that the
  990.                                                                                                                                                 //proper TextStyle be installed so
  991.                                                                                                                                                 //just do it so you don't forget
  992.                                                                                                                                                 //about it.
  993.                 twistDownControl -> UpdateControlSizeTo();        //sets fSize of twistDownControl
  994.                 twistDownControl -> UpdateControlLocationTo(rowNumber);    //sets fCoordinatesAreInvalid
  995.  
  996.             }
  997.             
  998.         if (twistDownElement -> TestShowSubListFlag())
  999.             this -> UpdateTwistDownElements(twistDownElement -> GetDescendantElement(), rowNumber);
  1000.             
  1001.         twistDownElement = twistDownElement -> GetSuccessorElement();
  1002.     }    
  1003.  
  1004. }
  1005. //----------------------------------------------------------------------------------------
  1006. // TTwistDownDocument::CalculateColWidthParams: called by TTwistDownView::CalculateColumnWidth
  1007. //----------------------------------------------------------------------------------------
  1008. //This routine scans the visible list and returns the greatest value for the indentLevel it
  1009. //finds along with the width of the largest twistDownElement -> fDisplayedText. The intent
  1010. //is to use that information to intelligently set the column width in the twistDownView.
  1011. //It has been tested but is not currently being used.
  1012. #pragma segment ARes
  1013. void TTwistDownDocument::CalculateColWidthParams(TTwistDownElement* twistDownElement, short& maxIndentLevel, 
  1014.                                                                                                                             short& maxTextWidth)                     
  1015. {
  1016. while (twistDownElement != NULL) 
  1017.     {
  1018.         short indentLevel = twistDownElement -> GetIndentLevel();
  1019.         if (indentLevel > maxIndentLevel)
  1020.             maxIndentLevel = indentLevel;
  1021.         
  1022.         CStr63    displayedText = gEmptyString;
  1023.         twistDownElement -> GetDisplayedText(displayedText);
  1024.         short stringWidth = StringWidth(displayedText);
  1025.         if (stringWidth > maxTextWidth)
  1026.             maxTextWidth = stringWidth;
  1027.             
  1028.         if (twistDownElement -> TestShowSubListFlag())
  1029.             this -> CalculateColWidthParams(twistDownElement -> GetDescendantElement(), maxIndentLevel, maxTextWidth);
  1030.             
  1031.         twistDownElement = twistDownElement -> GetSuccessorElement();
  1032.     }    
  1033. }
  1034. //----------------------------------------------------------------------------------------
  1035. // TTwistDownDocument::IncrementItemsInList: 
  1036. //----------------------------------------------------------------------------------------
  1037. #pragma segment AOpen
  1038. void  TTwistDownDocument::IncrementItemsInList()
  1039. {
  1040. fNumberOfItemsInList++;
  1041. }
  1042. //----------------------------------------------------------------------------------------
  1043. // TTwistDownDocument::DecrementItemsInList: 
  1044. //----------------------------------------------------------------------------------------
  1045. #pragma segment AClose
  1046. void  TTwistDownDocument::DecrementItemsInList()
  1047. {
  1048. fNumberOfItemsInList--;
  1049. }
  1050. //----------------------------------------------------------------------------------------
  1051. // TTwistDownDocument::GetNumberOfDirectoriesInList: 
  1052. //----------------------------------------------------------------------------------------
  1053. #pragma segment ARes
  1054. long TTwistDownDocument::GetNumberOfDirectoriesInList()
  1055. {
  1056. return fNumberOfDirectoriesInList;
  1057. }
  1058. //----------------------------------------------------------------------------------------
  1059. // TTwistDownDocument::GetNumberOfItemsInList: 
  1060. //----------------------------------------------------------------------------------------
  1061. #pragma segment ARes
  1062. long TTwistDownDocument::GetNumberOfItemsInList()
  1063. {
  1064. return fNumberOfItemsInList;
  1065. }
  1066. //----------------------------------------------------------------------------------------
  1067. // TTwistDownDocument::DoScriptCommand:    Scripting Support    
  1068. //----------------------------------------------------------------------------------------
  1069. #pragma segment MAScriptingRes
  1070. void TTwistDownDocument::DoScriptCommand(CommandNumber aCommandNumber, TAppleEvent* message, TAppleEvent* reply)
  1071. {
  1072.  
  1073. switch (aCommandNumber)
  1074.     {
  1075.         case cExpandAll:
  1076.             {
  1077.             //If fCouldExpandAll == TRUE then we most certainly will not be adding too many rows.
  1078.             //However, TExpandAllCommand::DoIt also checks - overkill???
  1079.                 if (fTwistDownView -> fCouldExpandAll) 
  1080.                     {
  1081.                         long objectHeapSpaceRequired = long((this -> GetNumberOfDirectoriesInList() 
  1082.                                                             - fTwistDownView -> GetNumberOfControls())*(gTwistDownApp -> fTDControlClassSize));
  1083.                                                                                     
  1084.                         Boolean haveHeapSpace = HaveObjectHeapSpace(objectHeapSpaceRequired + 3*1024);
  1085.  
  1086.                         if (haveHeapSpace)
  1087.                             {
  1088.                                 TExpandAllCommand* anExpandAllCommand = new TExpandAllCommand;
  1089.                                 anExpandAllCommand -> IExpandAllCommand(this,fTwistDownView, 
  1090.                                                                                                                 message -> fMessage, reply -> fMessage);
  1091.                                 
  1092.                                 this -> PostCommand(anExpandAllCommand);                            
  1093.                             }
  1094.                         else
  1095.                             Failure(memFullErr, 0);                        
  1096.                     }
  1097.                 else
  1098.                     FailOSErr(errListAlreadyExpanded);
  1099.             }
  1100.             break;
  1101.             
  1102.         case cCollapseAll:
  1103.             {
  1104.                 if (fTwistDownView -> fCouldCollapseAll)
  1105.                     {
  1106.                     //Because we don't want this to fail for out of memory reasons,
  1107.                     //allocate it from temporary memory.    //PGMacApp 550
  1108.                         Boolean oldTemp = TemporaryAllocation(TRUE);
  1109.                         Boolean oldArrayPerm = AllocateObjectsFromPerm(FALSE);
  1110.                             TCollapseAllCommand* aCollapseAllCommand = new TCollapseAllCommand;
  1111.                             aCollapseAllCommand -> ICollapseAllCommand(this, fTwistDownView, 
  1112.                                                                                                                 message -> fMessage, reply -> fMessage);                            
  1113.                             
  1114.                             this -> PostCommand(aCollapseAllCommand);
  1115.                         oldArrayPerm = AllocateObjectsFromPerm(oldArrayPerm);    
  1116.                         oldTemp = TemporaryAllocation(oldTemp);
  1117.                     }
  1118.                 else
  1119.                     FailOSErr(errListAlreadyCollapsed);
  1120.             }
  1121.             break;
  1122.                 
  1123.         default:
  1124.             {        
  1125.             Inherited::DoScriptCommand(aCommandNumber, message, reply);
  1126.             }
  1127.             break;
  1128.     }
  1129.  
  1130. }
  1131. //----------------------------------------------------------------------------------------
  1132. //Note: The following four methods:
  1133. //
  1134. //GetTwistDownElementByName,
  1135. //GetTwistDownElementByIndex,
  1136. //GetVisibleTwistDownElementByName, and
  1137. //GetVisibleTwistDownElementByIndex
  1138. //
  1139. //would not exist if Scripting were not supported. Each twistDownElement in the list has
  1140. //an absolute position established when the list is read. However, the whole list is not
  1141. //always visible to the user. Now, if a user were to expand a twistDownElement that is not
  1142. //visible, the view would not change and he might be expecting a change. This could cause
  1143. //confusion. One solution would be to make it visible by expanding all the twistDownElements
  1144. //in the chain above the target twistDownElement. At this point, I don't like that idea.
  1145. //The solution chosen here, is to allow the user to specify a search method of either just 
  1146. //the visible list or the whole list. The default is to search only the visible list.
  1147. //
  1148. //If the user chooses to search the whole list, when expanding or collapsing a twistDownElement,
  1149. //and the twistDownElement is not visible, the expansion or collapse of the element takes
  1150. //place but is not visible to the user at that time. However, if the user then expands
  1151. //all the elements in the chain above the target twistDownElement, the effect will then be
  1152. //seen (revealed). 
  1153. //
  1154. //This situation clearly illustrates a situation where scripting support must go beyond the
  1155. //capabilities of the user interface. In other words, it is not possible for the user to
  1156. //expand or collapse a twistDownElement that is not visible from the user interface.
  1157. //----------------------------------------------------------------------------------------
  1158. // TTwistDownDocument::GetTwistDownElementByName:        Scripting Support    
  1159. //----------------------------------------------------------------------------------------
  1160. #pragma segment ARes
  1161. void TTwistDownDocument::GetTwistDownElementByName(TTwistDownElement* startingTwistDownElement, 
  1162.                                                             TTwistDownElement** currentTwistDownElement, CStr63 &theName, Boolean &foundIt)
  1163. {
  1164. MAVolatileInit(TTwistDownElement*, twistDownElement, NULL);
  1165.  
  1166. twistDownElement = startingTwistDownElement;
  1167.  
  1168. while (twistDownElement != NULL && foundIt == FALSE) 
  1169.     {
  1170.         
  1171.         *currentTwistDownElement = twistDownElement;
  1172.         CStr63 aString = gEmptyString;
  1173.         twistDownElement -> GetDisplayedText(aString);
  1174.         if (aString == theName)
  1175.             foundIt = TRUE;
  1176.             
  1177.         if (twistDownElement -> GetDescendantElement() != NULL)
  1178.             this -> GetTwistDownElementByName(twistDownElement -> GetDescendantElement(), currentTwistDownElement, 
  1179.                                                                                                                             theName, foundIt);
  1180.         
  1181.         twistDownElement = twistDownElement -> GetSuccessorElement();
  1182.     }    
  1183.  
  1184. }
  1185. //----------------------------------------------------------------------------------------
  1186. // TTwistDownDocument::GetTwistDownElementByIndex:        Scripting Support    
  1187. //----------------------------------------------------------------------------------------
  1188. #pragma segment ARes
  1189. void TTwistDownDocument::GetTwistDownElementByIndex(short desiredIndex, 
  1190.                                                             TTwistDownElement* startingTwistDownElement, 
  1191.                                                             TTwistDownElement** currentTwistDownElement, 
  1192.                                                             short &elementCounter)
  1193. {
  1194. MAVolatileInit(TTwistDownElement*, twistDownElement, NULL);
  1195.  
  1196. twistDownElement = startingTwistDownElement;
  1197.  
  1198. while (twistDownElement != NULL && elementCounter != desiredIndex) 
  1199.     {
  1200.         ++elementCounter;
  1201.         *currentTwistDownElement = twistDownElement;
  1202.             
  1203.         if (twistDownElement -> GetDescendantElement() != NULL)
  1204.             this -> GetTwistDownElementByIndex(desiredIndex, twistDownElement -> GetDescendantElement(), 
  1205.                                                                             currentTwistDownElement, elementCounter);
  1206.         
  1207.         twistDownElement = twistDownElement -> GetSuccessorElement();
  1208.     }    
  1209.  
  1210. }
  1211. //----------------------------------------------------------------------------------------
  1212. // TTwistDownDocument::GetVisibleTwistDownElementByName:        Scripting Support    
  1213. //----------------------------------------------------------------------------------------
  1214. #pragma segment ARes
  1215. void TTwistDownDocument::GetVisibleTwistDownElementByName(TTwistDownElement* startingTwistDownElement, 
  1216.                                                             TTwistDownElement** currentTwistDownElement, CStr63 &theName, Boolean &foundIt)
  1217. {
  1218. MAVolatileInit(TTwistDownElement*, twistDownElement, NULL);
  1219.  
  1220. twistDownElement = startingTwistDownElement;
  1221.  
  1222. while (twistDownElement != NULL && foundIt == FALSE) 
  1223.     {
  1224.         
  1225.         *currentTwistDownElement = twistDownElement;
  1226.         CStr63 aString = gEmptyString;
  1227.         twistDownElement -> GetDisplayedText(aString);
  1228.         if (aString == theName)
  1229.             foundIt = TRUE;
  1230.             
  1231.         if (twistDownElement -> GetDescendantElement() != NULL && twistDownElement -> TestShowSubListFlag())
  1232.             this -> GetVisibleTwistDownElementByName(twistDownElement -> GetDescendantElement(), currentTwistDownElement, 
  1233.                                                                                                                             theName, foundIt);
  1234.         
  1235.         twistDownElement = twistDownElement -> GetSuccessorElement();
  1236.     }    
  1237.  
  1238. }
  1239. //----------------------------------------------------------------------------------------
  1240. // TTwistDownDocument::GetVisibleTwistDownElementByIndex:        Scripting Support    
  1241. //----------------------------------------------------------------------------------------
  1242. #pragma segment ARes
  1243. void TTwistDownDocument::GetVisibleTwistDownElementByIndex(short desiredIndex, TTwistDownElement* startingTwistDownElement, 
  1244.                                                             TTwistDownElement** currentTwistDownElement, short &elementCounter)
  1245. {
  1246. MAVolatileInit(TTwistDownElement*, twistDownElement, NULL);
  1247.  
  1248. twistDownElement = startingTwistDownElement;
  1249.  
  1250. while (twistDownElement != NULL && elementCounter != desiredIndex) 
  1251.     {
  1252.         ++elementCounter;
  1253.         *currentTwistDownElement = twistDownElement;
  1254.             
  1255.         if (twistDownElement -> GetDescendantElement() != NULL && twistDownElement -> TestShowSubListFlag())
  1256.             this -> GetVisibleTwistDownElementByIndex(desiredIndex, twistDownElement -> GetDescendantElement(), 
  1257.                                                                             currentTwistDownElement, elementCounter);
  1258.         
  1259.         twistDownElement = twistDownElement -> GetSuccessorElement();
  1260.     }    
  1261.  
  1262. }
  1263. //----------------------------------------------------------------------------------------
  1264. // TTwistDownDocument::GetObjectProperty:        Scripting Support
  1265. //----------------------------------------------------------------------------------------
  1266. #pragma segment MAScriptingRes
  1267.  
  1268. Boolean TTwistDownDocument::GetObjectProperty(CAEDesc& thePropertyValue,
  1269.                                         DescType whichProperty,
  1270.                                         const CAEDesc& desiredType)
  1271. {
  1272.     // Return properties for the twistDownView
  1273.     
  1274.     Boolean hasProperty = TRUE;
  1275.     
  1276.     FailInfo fi;
  1277.     Try(fi)
  1278.     {
  1279.         switch (whichProperty)
  1280.         {
  1281.  
  1282.             case pFontName:
  1283.                 CStr255 theFontName;
  1284.                 short theFontNum = fTextStyle.tsFont;
  1285.                 GetFontName(theFontNum, theFontName);
  1286.                 thePropertyValue.PutString(theFontName);
  1287.                 break;
  1288.                 
  1289.             case pPointSize:
  1290.                 long itsSize = (long)fTextStyle.tsSize;    
  1291.                 thePropertyValue.PutLong(itsSize);
  1292.                 break;                
  1293.  
  1294.             case pSearchMethod:
  1295.                 {
  1296.                     DescType theSearchMethod;
  1297.                     
  1298.                     if (fSearchMethod == visibleList)
  1299.                         theSearchMethod = kAEVisibleList;
  1300.                     else
  1301.                         theSearchMethod = kAEWholeList;
  1302.                         
  1303.                     thePropertyValue.PutEnum(theSearchMethod);
  1304.                 }
  1305.                 break;    
  1306.             
  1307.             case pNumFolders:
  1308.                     thePropertyValue.PutLong(fNumberOfDirectoriesInList);
  1309.                 break;    
  1310.                 
  1311.             case pNumFiles:
  1312.                     thePropertyValue.PutLong(fNumberOfFilesInList);
  1313.                 break;    
  1314.  
  1315.             case pNumItems:
  1316.                     thePropertyValue.PutLong(fNumberOfItemsInList);
  1317.                 break;
  1318.  
  1319.             default:
  1320.                 hasProperty = Inherited::GetObjectProperty(thePropertyValue, whichProperty, desiredType);
  1321.                 break;
  1322.         }
  1323.         fi.Success();
  1324.     }
  1325.     else
  1326.     {
  1327.         // we failed while trying to get the property
  1328.         hasProperty = FALSE;
  1329.         
  1330.         // Don't ReSignal
  1331.     }
  1332.     return hasProperty;
  1333. }
  1334. //----------------------------------------------------------------------------------------
  1335. // TTwistDownDocument::GetSetPropertyInfo:        Scripting Support
  1336. //----------------------------------------------------------------------------------------
  1337. #pragma segment MAScriptingRes
  1338. void TTwistDownDocument::GetSetPropertyInfo(DescType whichProperty,CommandNumber& cmdNum,
  1339.                                 Boolean& canUndo,Boolean& causesChange,TCommandHandler* &theContext)
  1340. {
  1341.  
  1342. switch(whichProperty)
  1343.     {
  1344.     
  1345.         case pFontName:
  1346.             cmdNum = cChangeFont;
  1347.             canUndo = FALSE;
  1348.             causesChange = FALSE;
  1349.             theContext = this;
  1350.             break;
  1351.             
  1352.         case pPointSize:
  1353.             cmdNum = cChangeFontSize;
  1354.             canUndo = FALSE;
  1355.             causesChange = FALSE;
  1356.             theContext = this;
  1357.             break;
  1358.  
  1359.         case pSearchMethod:
  1360.             cmdNum = cSetSearchMethod;
  1361.             canUndo = FALSE;
  1362.             causesChange = FALSE;
  1363.             theContext = this;
  1364.             break;
  1365.         
  1366.         default:
  1367.             Inherited::GetSetPropertyInfo(whichProperty, cmdNum, canUndo, causesChange, theContext);
  1368.             break;
  1369.     }
  1370. }
  1371. //----------------------------------------------------------------------------------------
  1372. // TTwistDownDocument::SetObjectProperty:        Scripting Support
  1373. //----------------------------------------------------------------------------------------
  1374. #pragma segment MAScriptingRes
  1375. void TTwistDownDocument::SetObjectProperty(const CAEDesc& thePropertyValue,DescType whichProperty)
  1376. {
  1377. //I'm ambivalent about whether it makes sense to allow a script to change the font or its size,
  1378. //if the list is empty. We wouldn't allow it from the menu. For the sake of argument, let's
  1379. //allow it here and not allow it in TTwistDownView::SetObjectProperty.
  1380.  
  1381. long numberOfItemsInList = numberOfItemsInList = this -> GetNumberOfItemsInList();
  1382.     
  1383. switch (whichProperty)
  1384.     {
  1385.  
  1386.             case pFontName:
  1387.                 CStr255 newFontName;
  1388.                 thePropertyValue.GetString(newFontName,255);
  1389. //                if (numberOfItemsInList > 0)
  1390.                     fTwistDownView -> DoChangeFont(newFontName);
  1391.                 break;
  1392.                 
  1393.             case pPointSize:
  1394.                 short newFontSize = 0;    
  1395.                 newFontSize = (short)thePropertyValue.GetLong();
  1396. //                if (numberOfItemsInList > 0)
  1397.                     fTwistDownView -> DoChangeFontSize(newFontSize);
  1398.                 break;                
  1399.  
  1400.             case pSearchMethod:
  1401.                 {
  1402.                     DescType theSearchMethod = thePropertyValue.GetEnum();
  1403.                     
  1404.                     if (theSearchMethod == kAEVisibleList)
  1405.                         fSearchMethod = visibleList;
  1406.                     else
  1407.                         fSearchMethod = wholeList;
  1408.                 }
  1409.                 break;    
  1410.                 
  1411.             case pNumFolders:
  1412.             case pNumFiles:
  1413.             case pNumItems:
  1414.                     FailOSErr(errAECantSetReadOnly);
  1415.                 break;
  1416.  
  1417.         default:
  1418.             Inherited::SetObjectProperty(thePropertyValue, whichProperty);
  1419.             break;
  1420.     }
  1421. }
  1422. //----------------------------------------------------------------------------------------
  1423. // TTwistDownDocument::GetIndContainedObject:    Scripting Support
  1424. //----------------------------------------------------------------------------------------
  1425. #pragma segment OSLDispatchRes
  1426.  
  1427. MScriptableObject* TTwistDownDocument::GetIndContainedObject(DescType desiredType,long index)
  1428. {
  1429.  
  1430.     MScriptableObject *indexedObject;
  1431.     
  1432.     switch(desiredType)
  1433.     {
  1434.         case cTwistDownView:
  1435.             {        
  1436.                 TTwistDownView* indexedTwistDownView = fTwistDownView;
  1437.                 indexedObject = indexedTwistDownView;
  1438.             }
  1439.             break;
  1440.  
  1441.         case cTwistDownElement:
  1442.             {
  1443.             
  1444.  
  1445.                 TTwistDownElement* currentTwistDownElement = NULL;
  1446.                 short theIndex = (short)index;
  1447.                 short elementCounter = 0;
  1448.                 
  1449.                 if (fSearchMethod == visibleList)
  1450.                     this -> GetVisibleTwistDownElementByIndex(theIndex, fHeadOfListElement, 
  1451.                                                                                                                 ¤tTwistDownElement, elementCounter);
  1452.                 else
  1453.             //Note: I should be able to do this using the fItemInList field of TTwistDownElement
  1454.             //instead of counting.                
  1455.                     this -> GetTwistDownElementByIndex(theIndex, fHeadOfListElement, 
  1456.                                                                                                                 ¤tTwistDownElement, elementCounter);
  1457.                 
  1458.                 indexedObject = currentTwistDownElement;
  1459.             }
  1460.             break;
  1461.             
  1462.         default:
  1463.             {
  1464.                 indexedObject = Inherited::GetIndContainedObject(desiredType, index);
  1465.             }
  1466.             break;
  1467.     }
  1468.     
  1469.     return indexedObject;
  1470. }
  1471. //----------------------------------------------------------------------------------------
  1472. // TTwistDownDocument::GetContainedObject:    Scripting Support
  1473. //----------------------------------------------------------------------------------------
  1474. #pragma segment OSLDispatchRes
  1475. MScriptableObject* TTwistDownDocument::GetContainedObject(DescType desiredType,DescType selectionForm,
  1476.                                                                                                                                     const CAEDesc& selectionData)
  1477. {    
  1478.  
  1479.     MScriptableObject * result = NULL;
  1480.     
  1481.     if (desiredType == cTwistDownView)
  1482.         {        
  1483.             TTwistDownView* resultTwistDownView = fTwistDownView;
  1484.             result = resultTwistDownView;
  1485.         }
  1486.         
  1487.     else if (desiredType == cTwistDownElement)
  1488.         {
  1489.         
  1490.             if (selectionForm == formName)
  1491.                 {
  1492.                     CStr255 theName = gEmptyString;
  1493.                     selectionData.GetString(theName);
  1494.                     TTwistDownElement* currentTwistDownElement = NULL;
  1495.                     Boolean foundIt = FALSE;
  1496.                     
  1497.                     if (fSearchMethod == visibleList)
  1498.                         this -> GetVisibleTwistDownElementByName(fHeadOfListElement, ¤tTwistDownElement, 
  1499.                                                                                                                                                 (CStr63 &)theName, foundIt);
  1500.                     else
  1501.                         this -> GetTwistDownElementByName(fHeadOfListElement, ¤tTwistDownElement, 
  1502.                                                                                                                                                 (CStr63 &)theName, foundIt);
  1503.  
  1504.                     if (foundIt == FALSE)
  1505.                         currentTwistDownElement = NULL;
  1506.  
  1507.                     result = currentTwistDownElement;
  1508.                 }
  1509.             else if (selectionForm == formAbsolutePosition)
  1510.                 {
  1511.                     //Note: I should be able to do this using the fItemInList field of TTwistDownElement
  1512.                     //instead of counting.
  1513.                     TTwistDownElement* currentTwistDownElement = NULL;
  1514.                     long index = selectionData.GetLong();
  1515.                     short theIndex = (short)index;
  1516.                     
  1517.                     if (theIndex <= fNumberOfItemsInList)
  1518.                         {
  1519.                             short elementCounter = 0;
  1520.                             
  1521.                             if (fSearchMethod == visibleList)
  1522.                                 this -> GetVisibleTwistDownElementByIndex(theIndex, fHeadOfListElement, 
  1523.                                                                                                                                 ¤tTwistDownElement, elementCounter);                                                    
  1524.                             else
  1525.                                 this -> GetTwistDownElementByIndex(theIndex, fHeadOfListElement, 
  1526.                                                                                                                                 ¤tTwistDownElement, elementCounter);
  1527.                         }
  1528.                         
  1529.                     result = currentTwistDownElement;        
  1530.  
  1531.                 }
  1532.         }
  1533.         
  1534.     else
  1535.         result = Inherited::GetContainedObject(desiredType, selectionForm, selectionData);
  1536.         
  1537.     return result;
  1538. }
  1539. //----------------------------------------------------------------------------------------
  1540. // TTwistDownDocument::CountContainedObjects: 
  1541. //----------------------------------------------------------------------------------------
  1542. #pragma segment MAScriptingRes
  1543.  
  1544. long TTwistDownDocument::CountContainedObjects(DescType desiredType)
  1545. {
  1546.  
  1547.     long result = 0;
  1548.  
  1549.     switch (desiredType)
  1550.     {
  1551.         case cTwistDownView:
  1552.             {
  1553.                 result = 1;
  1554.             }
  1555.             break;
  1556.  
  1557.         case cTwistDownElement:
  1558.             {
  1559.                 result = fNumberOfItemsInList;
  1560.             }
  1561.             break;
  1562.  
  1563.         default:
  1564.             {        
  1565.                 result = Inherited::CountContainedObjects(desiredType);
  1566.             }
  1567.             break;
  1568.     }
  1569.  
  1570.     return result;
  1571. }
  1572. //========================================================================================
  1573. // CLASS TExpandAllCommand    
  1574. //========================================================================================
  1575. #undef Inherited
  1576. #define Inherited TServerCommand
  1577.  
  1578. #pragma segment ARes
  1579. MA_DEFINE_CLASS_M1(TExpandAllCommand, Inherited);
  1580. //----------------------------------------------------------------------------------------
  1581. // TExpandAllCommand::TExpandAllCommand: 
  1582. //----------------------------------------------------------------------------------------
  1583. #pragma segment ARes
  1584. TExpandAllCommand::TExpandAllCommand()
  1585. {
  1586. fTwistDownView = NULL;
  1587. fTwistDownDocument = NULL;
  1588.  
  1589. fOldNumberOfExpandedControls = 0;
  1590. fOldNumberOfCollapsedControls = 0;
  1591.  
  1592. #if qDebug
  1593. this -> PrintAppConstructorClassInfo();
  1594. #endif
  1595. }
  1596. //----------------------------------------------------------------------------------------
  1597. // TExpandAllCommand::~TExpandAllCommand: 
  1598. //----------------------------------------------------------------------------------------
  1599. #pragma segment ARes
  1600. TExpandAllCommand::~TExpandAllCommand()
  1601. {
  1602.  
  1603. fTwistDownView = NULL;
  1604. fTwistDownDocument = NULL;
  1605.  
  1606. fOldNumberOfExpandedControls = 0;
  1607. fOldNumberOfCollapsedControls = 0;
  1608.  
  1609. #if qDebug
  1610. this -> PrintAppDestructorClassInfo();
  1611. #endif
  1612. }
  1613. //----------------------------------------------------------------------------------------
  1614. //    TExpandAllCommand::IExpandAllCommand:    
  1615. //----------------------------------------------------------------------------------------
  1616. #pragma segment ASelCommand
  1617. void TExpandAllCommand::IExpandAllCommand(TTwistDownDocument* twistDownDocument, TCommandHandler* itsContext)
  1618. {
  1619. this -> IServerCommand(cExpandAll,itsContext,kCantUndo, kDoesNotCauseChange,NULL);
  1620.  
  1621. fTwistDownDocument = twistDownDocument;
  1622. fTwistDownView = twistDownDocument -> fTwistDownView;
  1623.  
  1624. fOldNumberOfExpandedControls = fTwistDownView -> GetNumberOfExpandedControls();
  1625. fOldNumberOfCollapsedControls = fTwistDownView -> GetNumberOfCollapsedControls();
  1626.                                                         
  1627. }
  1628.  
  1629. //----------------------------------------------------------------------------------------
  1630. //    TExpandAllCommand::IExpandAllCommand:    
  1631. //----------------------------------------------------------------------------------------
  1632. #pragma segment ASelCommand
  1633. void TExpandAllCommand::IExpandAllCommand(TTwistDownDocument* twistDownDocument, TCommandHandler* itsContext, 
  1634.                                                                                     const AppleEvent& itsMessage, const AppleEvent& itsReply)
  1635. {
  1636. fSuspendTheEvent = TRUE;    //For debugging fun and games, comment this out. Everything
  1637.                                                     //will work fine until you encounter low memory conditions
  1638.                                                     //and fail. Then all bets are off. Note that it must be set
  1639.                                                     //before IServerCommand is called.
  1640.  
  1641. this -> IServerCommand(cExpandAll,itsContext,kCantUndo, kDoesNotCauseChange,NULL,itsMessage,itsReply);
  1642.  
  1643.  
  1644.                                                     
  1645. fTwistDownDocument = twistDownDocument;
  1646. fTwistDownView = twistDownDocument -> fTwistDownView;
  1647.  
  1648. fOldNumberOfExpandedControls = fTwistDownView -> GetNumberOfExpandedControls();
  1649. fOldNumberOfCollapsedControls = fTwistDownView -> GetNumberOfCollapsedControls();
  1650.  
  1651. }
  1652.  
  1653. //----------------------------------------------------------------------------------------
  1654. // TExpandAllCommand::MakeAppleEvent:        Scripting Support    
  1655. //----------------------------------------------------------------------------------------
  1656. #pragma segment ACommandRes
  1657. TAppleEvent* TExpandAllCommand::MakeAppleEvent()
  1658. {
  1659.     MAVolatileInit(TAppleEvent*, theExpandAllEvent, NULL);
  1660.     
  1661.     FailInfo fi;
  1662.         Try(fi)
  1663.         {
  1664.             theExpandAllEvent = new TAppleEvent;
  1665.             theExpandAllEvent -> IAppleEvent(kAETwistDownListsSuite, kAEExpandAllID,gServerAddress, kAENoReply);
  1666.             {
  1667.                 CTempDesc    directObjectDesc;
  1668.                 if (gAppleEventRouting == routeToDoc)
  1669.                     fTwistDownDocument -> MakeObjectSpecifier(directObjectDesc, fTwistDownDocument -> GetSpecifierForm());
  1670.                 else if (gAppleEventRouting == routeToView)
  1671.                     fTwistDownView -> MakeObjectSpecifier(directObjectDesc, fTwistDownView -> GetSpecifierForm());
  1672.     
  1673.                 theExpandAllEvent -> WriteParameter(keyDirectObject, directObjectDesc);
  1674.             }
  1675.             fi.Success();
  1676.         }
  1677.         else // Recover
  1678.         {
  1679.             theExpandAllEvent = (TAppleEvent *)FreeIfObject(theExpandAllEvent);
  1680.             fi.ReSignal();
  1681.         }
  1682.         
  1683.     return theExpandAllEvent;
  1684.     
  1685. }
  1686. //----------------------------------------------------------------------------------------
  1687. //    TExpandAllCommand::DoIt:    
  1688. //----------------------------------------------------------------------------------------
  1689. #pragma segment ADoCommand
  1690. void TExpandAllCommand::DoIt()
  1691. {
  1692. OSErr myOSErr = noErr;
  1693. TTwistDownElement* headOfListElement = fTwistDownDocument -> GetHeadOfList();
  1694. short rowNumber = 0;
  1695.  
  1696. FailInfo fi;
  1697. Try(fi)
  1698.     {
  1699. //Note: The following test is here only to support scripting. DoMenuCommand support does not
  1700. //require this test because the fCouldExpandAll flag will be FALSE if the number of items
  1701. //in the list exceeds the capacity of TTextListView. In other words, if there are too many 
  1702. //rows to display, you can't get here from the menu and you shouldn't be able to get here
  1703. //from DoScriptCommand either because DoScriptCommand tests fCouldExpandAll before even
  1704. //making the TExpandAllCommand. 
  1705.         if (fTwistDownDocument -> GetNumberOfItemsInList() <= (long)kMaxNumberOfItemsToDisplay)
  1706.             {
  1707.                 //Step 1: For all TTwistDownElements for which fHasSubList is TRUE, set fShowSubList to TRUE.
  1708.                 fTwistDownDocument -> SetShowSubListFlags(headOfListElement);    
  1709.                                                                                                                                     
  1710.                 //Step 2: Make and add the new controls to the twistDownView (with the proper locations.)    
  1711.                 rowNumber = 0;
  1712.  
  1713.                 fTwistDownView -> AddTwistDownControls(headOfListElement, rowNumber, myOSErr);                                                                                                        
  1714.  
  1715.                 if (myOSErr != noErr)
  1716.                     Failure(myOSErr, 0);
  1717.                     
  1718.                 //Step 3: Uupdate the locations of all the controls.
  1719.                 rowNumber = 0;        
  1720.                 fTwistDownView -> UpdateTwistDownControlLocations(headOfListElement, rowNumber); 
  1721.  
  1722.                 //Step 4: Insert rows as required in front of rowNumber unless it
  1723.                 //is beyond the end of the currently displayed list. In that
  1724.                 //case, the rows are inserted last.
  1725.                 rowNumber = 1;                                                                                                                                
  1726.                 myOSErr = fTwistDownView -> BuildVisibleList(rowNumber);                                                            
  1727.         
  1728.                 //Step 5: Adjust the size of the view to accomodate the exact number of rows.
  1729.                 fTwistDownView -> ResizeTwistDownViewRows();
  1730.         
  1731.                 //just set fNumberOfExpandedControls to fNumberOfDirectoriesInList
  1732.                 //and set fNumberOfCollapsedControls to 0.
  1733.                 fTwistDownView -> SetCantExpandAll();    //Will cause the cExpandAll command to be disabled.
  1734.             }
  1735.         else
  1736.             {
  1737.                 myOSErr = errTooManyRows;
  1738.                 Failure(errTooManyRows, msgTooManyRows);
  1739.             }
  1740.         
  1741.         fi.Success();
  1742.     }
  1743. else
  1744.     {    //Situation: For all twistDownElements for which fHasSubList if TRUE, fOldShowSubList
  1745.         //has been set to fShowSubList and then fShowSubList has been set to TRUE. New twistDownControls
  1746.         //may have been added to the twistDownView. If failure occurred on the first attempt
  1747.         //to AddTwistDownControls, no new twistDownControls will have been added. The failure
  1748.         //handler in AddTwistDownControls will have freed the offending control.
  1749.         //
  1750.         //To recover, we need to remove twistDownControls from from all twistDownElements 
  1751.         //whose fOldShowSubList flag is set to FALSE. Then fShowSubList must be set to the
  1752.         //value of fOldShowSubList and then fOldShowSubList must be set to FALSE.
  1753.         
  1754.         //There are two kinds of errors that bring us here. In the case of errTooManyRows, nothing
  1755.         //has been done to the list and we skip over the following steps and ReSignal. In the other case
  1756.         //An out of memory condition may be signaled by AddTwistDownControls. In that case the prior state
  1757.         //of the list must be restored.
  1758.         if (myOSErr != errTooManyRows)
  1759.             {
  1760.                 //Step 1: Remove the unwanted twistDownControls. A failure in AddTwistDownControls will have 
  1761.                 //freed the offending twistDownControl before we get here.
  1762.         
  1763.                 fTwistDownView -> RestoreTwistDownControls(headOfListElement);
  1764.         
  1765.                 //Step 2: Restore the fShowSubList flags to their previous setting and set fOldShowSubList
  1766.                 //to FALSE.
  1767.  
  1768.                 fTwistDownDocument -> RestoreShowSubListFlags(headOfListElement);
  1769.  
  1770.                 fTwistDownView -> SetNumberOfExpandedControlsTo(fOldNumberOfExpandedControls);
  1771.                 fTwistDownView -> SetNumberOfCollapsedControlsTo(fOldNumberOfCollapsedControls);
  1772.                 fTwistDownView -> SetTheCouldFlags();
  1773.             }
  1774.         fi.ReSignal();
  1775.     }
  1776. }
  1777. //========================================================================================
  1778. // CLASS TCollapseAllCommand    
  1779. //========================================================================================
  1780. #undef Inherited
  1781. #define Inherited TServerCommand
  1782.  
  1783. #pragma segment ARes
  1784. MA_DEFINE_CLASS_M1(TCollapseAllCommand, Inherited);
  1785. //----------------------------------------------------------------------------------------
  1786. // TCollapseAllCommand::TCollapseAllCommand: 
  1787. //----------------------------------------------------------------------------------------
  1788. #pragma segment ARes
  1789. TCollapseAllCommand::TCollapseAllCommand()
  1790. {
  1791. fTwistDownDocument = NULL;
  1792.  
  1793. #if qDebug
  1794. this -> PrintAppConstructorClassInfo();
  1795. #endif
  1796. }
  1797. //----------------------------------------------------------------------------------------
  1798. // TCollapseAllCommand::~TCollapseAllCommand: 
  1799. //----------------------------------------------------------------------------------------
  1800. #pragma segment ARes
  1801. TCollapseAllCommand::~TCollapseAllCommand()
  1802. {
  1803. fTwistDownDocument = NULL;
  1804. fTwistDownView = NULL;
  1805. #if qDebug
  1806. this -> PrintAppDestructorClassInfo();
  1807. #endif
  1808. }
  1809. //----------------------------------------------------------------------------------------
  1810. //    TCollapseAllCommand::ICollapseAllCommand:    
  1811. //----------------------------------------------------------------------------------------
  1812. #pragma segment ASelCommand
  1813. void TCollapseAllCommand::ICollapseAllCommand(TTwistDownDocument* twistDownDocument, TCommandHandler* itsContext)
  1814. {
  1815. this -> IServerCommand(cCollapseAll,itsContext,kCantUndo, kDoesNotCauseChange,NULL);
  1816.  
  1817. fTwistDownDocument = twistDownDocument;
  1818. fTwistDownView = twistDownDocument -> fTwistDownView;
  1819. }
  1820. //----------------------------------------------------------------------------------------
  1821. //    TCollapseAllCommand::ICollapseAllCommand:    
  1822. //----------------------------------------------------------------------------------------
  1823. #pragma segment ASelCommand
  1824. void TCollapseAllCommand::ICollapseAllCommand(TTwistDownDocument* twistDownDocument, TCommandHandler* itsContext, 
  1825.                                                                                         const AppleEvent& itsMessage, const AppleEvent& itsReply)
  1826. {
  1827. fSuspendTheEvent = TRUE;    //For debugging fun and games, comment this out. Everything
  1828.                                                     //will work fine until you encounter low memory conditions
  1829.                                                     //and fail. Then all bets are off. Note that it must be set
  1830.                                                     //before IServerCommand is called.
  1831.                                                     
  1832. this -> IServerCommand(cCollapseAll,itsContext,kCantUndo, kDoesNotCauseChange,NULL,itsMessage,itsReply);
  1833.  
  1834. fTwistDownDocument = twistDownDocument;
  1835. fTwistDownView = twistDownDocument -> fTwistDownView;
  1836. }
  1837. //----------------------------------------------------------------------------------------
  1838. // TCollapseAllCommand::MakeAppleEvent:        Scripting Support    
  1839. //----------------------------------------------------------------------------------------
  1840. #pragma segment ACommandRes
  1841. TAppleEvent* TCollapseAllCommand::MakeAppleEvent()
  1842. {
  1843.  
  1844.     MAVolatileInit(TAppleEvent*, theCollapseAllEvent, NULL);
  1845.  
  1846.     FailInfo fi;
  1847.         Try(fi)
  1848.         {    
  1849.  
  1850.             theCollapseAllEvent = new TAppleEvent;    
  1851.             theCollapseAllEvent -> IAppleEvent(kAETwistDownListsSuite, kAECollapseAllID,gServerAddress, kAENoReply);
  1852.             {
  1853.                 CTempDesc    directObjectDesc;
  1854.                 if (gAppleEventRouting == routeToDoc)
  1855.                     fTwistDownDocument -> MakeObjectSpecifier(directObjectDesc, fTwistDownDocument -> GetSpecifierForm());
  1856.                 else if (gAppleEventRouting == routeToView)
  1857.                     fTwistDownView -> MakeObjectSpecifier(directObjectDesc, fTwistDownView -> GetSpecifierForm());
  1858.  
  1859.             theCollapseAllEvent -> WriteParameter(keyDirectObject, directObjectDesc);
  1860.             }
  1861.             fi.Success();
  1862.         }
  1863.         else // Recover
  1864.         {
  1865.             theCollapseAllEvent = (TAppleEvent *)FreeIfObject(theCollapseAllEvent);
  1866.             fi.ReSignal();
  1867.         }
  1868.         
  1869.     return theCollapseAllEvent;
  1870.  
  1871. }
  1872. //----------------------------------------------------------------------------------------
  1873. //    TCollapseAllCommand::DoIt:    
  1874. //----------------------------------------------------------------------------------------
  1875. #pragma segment ADoCommand
  1876. void TCollapseAllCommand::DoIt()
  1877. {
  1878.  
  1879.     fTwistDownDocument -> CollapseAll();
  1880.     //just set fNumberOfCollapsedControls to fInitialNumberOfControls
  1881.     //and set fNumberOfExpandedControls to 0.
  1882.     fTwistDownView -> SetCantCollapseAll();    //Will cause the cCollapseAll command to be disabled.
  1883.         
  1884. }
  1885. //========================================================================================
  1886. // CLASS TExpandElementCommand    
  1887. //========================================================================================
  1888. #undef Inherited
  1889. #define Inherited TServerCommand
  1890.  
  1891. #pragma segment ARes
  1892. MA_DEFINE_CLASS_M1(TExpandElementCommand, Inherited);
  1893. //----------------------------------------------------------------------------------------
  1894. // TExpandElementCommand::TExpandElementCommand: 
  1895. //----------------------------------------------------------------------------------------
  1896. #pragma segment ARes
  1897. TExpandElementCommand::TExpandElementCommand()
  1898. {
  1899. fTwistDownDocument = NULL;
  1900. fTwistDownView = NULL;
  1901. fElementToExpand = NULL;
  1902.  
  1903. fOldNumberOfExpandedControls = 0;
  1904. fOldNumberOfCollapsedControls = 0;
  1905.  
  1906. #if qDebug
  1907. this -> PrintAppConstructorClassInfo();
  1908. #endif
  1909. }
  1910. //----------------------------------------------------------------------------------------
  1911. // TExpandElementCommand::~TExpandElementCommand: 
  1912. //----------------------------------------------------------------------------------------
  1913. #pragma segment ARes
  1914. TExpandElementCommand::~TExpandElementCommand()
  1915. {
  1916. fTwistDownDocument = NULL;
  1917. fTwistDownView = NULL;
  1918. fElementToExpand = NULL;
  1919.  
  1920. fOldNumberOfExpandedControls = 0;
  1921. fOldNumberOfCollapsedControls = 0;
  1922.  
  1923. #if qDebug
  1924. this -> PrintAppDestructorClassInfo();
  1925. #endif
  1926. }
  1927. //----------------------------------------------------------------------------------------
  1928. //    TExpandElementCommand::IExpandElementCommand:    
  1929. //----------------------------------------------------------------------------------------
  1930. #pragma segment ASelCommand
  1931. void TExpandElementCommand::IExpandElementCommand(TTwistDownDocument* twistDownDocument, 
  1932.                                                     TTwistDownElement* elementToExpand)
  1933. {
  1934.  
  1935. this -> IServerCommand(cExpandElement,fTwistDownDocument,kCantUndo, kDoesNotCauseChange,NULL);
  1936.  
  1937. fTwistDownDocument = twistDownDocument;
  1938. fTwistDownView = twistDownDocument -> fTwistDownView;
  1939. fElementToExpand = elementToExpand;
  1940.  
  1941. fOldNumberOfExpandedControls = fTwistDownView -> GetNumberOfExpandedControls();
  1942. fOldNumberOfCollapsedControls = fTwistDownView -> GetNumberOfCollapsedControls();
  1943. }
  1944. //----------------------------------------------------------------------------------------
  1945. //    TExpandElementCommand::IExpandElementCommand:    
  1946. //----------------------------------------------------------------------------------------
  1947. #pragma segment ASelCommand
  1948. void TExpandElementCommand::IExpandElementCommand(TTwistDownDocument* twistDownDocument, 
  1949.                                                                         TTwistDownElement* elementToExpand, const AppleEvent& itsMessage, 
  1950.                                                                         const AppleEvent& itsReply)
  1951. {
  1952. fSuspendTheEvent = TRUE;    //For debugging fun and games, comment this out. Everything
  1953.                                                     //will work fine until you encounter low memory conditions
  1954.                                                     //and fail. Then all bets are off. Note that it must be set
  1955.                                                     //before IServerCommand is called.
  1956.                                                     
  1957. this -> IServerCommand(cExpandElement,twistDownDocument,kCantUndo,kDoesNotCauseChange,NULL,
  1958.                                                                                                                                                 itsMessage,itsReply);
  1959.  
  1960. fTwistDownDocument = twistDownDocument;
  1961. fTwistDownView = twistDownDocument -> fTwistDownView;
  1962. fElementToExpand = elementToExpand;
  1963.  
  1964. fOldNumberOfExpandedControls = fTwistDownView -> GetNumberOfExpandedControls();
  1965. fOldNumberOfCollapsedControls = fTwistDownView -> GetNumberOfCollapsedControls();
  1966. }
  1967. //----------------------------------------------------------------------------------------
  1968. // TExpandElementCommand::MakeAppleEvent:        Scripting Support    
  1969. //----------------------------------------------------------------------------------------
  1970. #pragma segment ACommandRes
  1971. TAppleEvent* TExpandElementCommand::MakeAppleEvent()
  1972. {
  1973.     MAVolatileInit(TAppleEvent*, theExpandElementEvent, NULL);
  1974.     
  1975.     FailInfo fi;
  1976.         Try(fi)
  1977.         {
  1978.             theExpandElementEvent = new TAppleEvent;
  1979.             theExpandElementEvent -> IAppleEvent(kAETwistDownListsSuite, kAEExpandElementID,gServerAddress, kAENoReply);
  1980.             {
  1981.                 
  1982.                 CTempDesc    targetObjectDesc;        
  1983.                 fElementToExpand -> MakeObjectSpecifier(targetObjectDesc, fElementToExpand -> GetSpecifierForm());
  1984.                 theExpandElementEvent -> WriteParameter(keyDirectObject, targetObjectDesc);    
  1985.  
  1986.             }
  1987.             fi.Success();
  1988.         }
  1989.         else // Recover
  1990.         {
  1991.             theExpandElementEvent = (TAppleEvent *)FreeIfObject(theExpandElementEvent);
  1992.             fi.ReSignal();
  1993.         }
  1994.         
  1995.     return theExpandElementEvent;
  1996.     
  1997. }
  1998. //----------------------------------------------------------------------------------------
  1999. //    TExpandElementCommand::DoIt:    
  2000. //----------------------------------------------------------------------------------------
  2001. #pragma segment ADoCommand
  2002. void TExpandElementCommand::DoIt()
  2003. {
  2004. FailInfo fi;
  2005. Try(fi)
  2006.     {    
  2007.         fTwistDownDocument -> ExpandElement(fElementToExpand);
  2008.         //I've got to increment fNumberOfExpandedControls here 
  2009.         //and decrement fNumberOfCollapsedControls here to account for the 
  2010.         //twistDownControl being expanded. All other controls will
  2011.         //take care of themselves.
  2012.         fTwistDownView -> IncrementNumberOfExpandedControls();
  2013.         fTwistDownView -> DecrementNumberOfCollapsedControls();
  2014.         fTwistDownView -> SetTheCouldFlags();
  2015.         
  2016.         fi.Success();
  2017.     }
  2018. else
  2019.     {
  2020.         //If there is a failure, it most likely will occur because an out of memory condition
  2021.         //occurred while making a new control. To recover, we need to collapse the twistDownElement.
  2022.         fTwistDownDocument -> CollapseElement(fElementToExpand);
  2023.         fTwistDownView -> SetNumberOfExpandedControlsTo(fOldNumberOfExpandedControls);
  2024.         fTwistDownView -> SetNumberOfCollapsedControlsTo(fOldNumberOfCollapsedControls);
  2025.         fTwistDownView -> SetTheCouldFlags();
  2026.         fi.ReSignal();
  2027.     }
  2028. }
  2029. //========================================================================================
  2030. // CLASS TCollapseElementCommand    
  2031. //========================================================================================
  2032. #undef Inherited
  2033. #define Inherited TServerCommand
  2034.  
  2035. #pragma segment ARes
  2036. MA_DEFINE_CLASS_M1(TCollapseElementCommand, Inherited);
  2037. //----------------------------------------------------------------------------------------
  2038. // TCollapseElementCommand::TCollapseElementCommand: 
  2039. //----------------------------------------------------------------------------------------
  2040. #pragma segment ARes
  2041. TCollapseElementCommand::TCollapseElementCommand()
  2042. {
  2043. fTwistDownDocument = NULL;
  2044. fTwistDownView = NULL;
  2045. fElementToCollapse = NULL;
  2046.  
  2047. #if qDebug
  2048. this -> PrintAppConstructorClassInfo();
  2049. #endif
  2050. }
  2051. //----------------------------------------------------------------------------------------
  2052. // TCollapseElementCommand::~TCollapseElementCommand: 
  2053. //----------------------------------------------------------------------------------------
  2054. #pragma segment ARes
  2055. TCollapseElementCommand::~TCollapseElementCommand()
  2056. {
  2057. fTwistDownDocument = NULL;
  2058. fTwistDownView = NULL;
  2059. fElementToCollapse = NULL;
  2060.  
  2061. #if qDebug
  2062. this -> PrintAppDestructorClassInfo();
  2063. #endif
  2064. }
  2065. //----------------------------------------------------------------------------------------
  2066. //    TCollapseElementCommand::ICollapseElementCommand:    
  2067. //----------------------------------------------------------------------------------------
  2068. #pragma segment ASelCommand
  2069. void TCollapseElementCommand::ICollapseElementCommand(TTwistDownDocument* twistDownDocument, 
  2070.                                                         TTwistDownElement* elementToCollapse)
  2071. {
  2072. this -> IServerCommand(cCollapseElement,twistDownDocument,kCantUndo, kDoesNotCauseChange,NULL);
  2073. fTwistDownDocument = twistDownDocument;
  2074. fTwistDownView = twistDownDocument -> fTwistDownView;
  2075. fElementToCollapse = elementToCollapse;
  2076. }
  2077. //----------------------------------------------------------------------------------------
  2078. //    TCollapseElementCommand::ICollapseElementCommand:    
  2079. //----------------------------------------------------------------------------------------
  2080. #pragma segment ASelCommand
  2081. void TCollapseElementCommand::ICollapseElementCommand(TTwistDownDocument* twistDownDocument, 
  2082.                                                     TTwistDownElement* elementToCollapse, const AppleEvent& itsMessage, 
  2083.                                                                             const AppleEvent& itsReply)
  2084. {
  2085. fSuspendTheEvent = TRUE;    //For debugging fun and games, comment this out. Everything
  2086.                                                     //will work fine until you encounter low memory conditions
  2087.                                                     //and fail. Then all bets are off. Note that it must be set
  2088.                                                     //before IServerCommand is called.
  2089.                                                     
  2090. this -> IServerCommand(cCollapseElement,twistDownDocument,kCantUndo,kDoesNotCauseChange,NULL,
  2091.                                                                                                                                                 itsMessage,itsReply);
  2092.  
  2093. fTwistDownDocument = twistDownDocument;
  2094. fTwistDownView = twistDownDocument -> fTwistDownView;
  2095. fElementToCollapse = elementToCollapse;                                                    
  2096. }
  2097. //----------------------------------------------------------------------------------------
  2098. // TCollapseElementCommand::MakeAppleEvent:        Scripting Support    
  2099. //----------------------------------------------------------------------------------------
  2100. #pragma segment ACommandRes
  2101. TAppleEvent* TCollapseElementCommand::MakeAppleEvent()
  2102. {
  2103.  
  2104.     MAVolatileInit(TAppleEvent*, theCollapseElementEvent, NULL);
  2105.     
  2106.     FailInfo fi;
  2107.         Try(fi)
  2108.         {
  2109.             theCollapseElementEvent = new TAppleEvent;
  2110.             theCollapseElementEvent -> IAppleEvent(kAETwistDownListsSuite,kAECollapseElementID,gServerAddress,kAENoReply);
  2111.             {
  2112.                 
  2113.                 CTempDesc    directObjectDesc;        
  2114.                 fElementToCollapse -> MakeObjectSpecifier(directObjectDesc, fElementToCollapse -> GetSpecifierForm());
  2115.                 theCollapseElementEvent -> WriteParameter(keyDirectObject, directObjectDesc);    
  2116.  
  2117.             }
  2118.             fi.Success();
  2119.         }
  2120.         else // Recover
  2121.         {
  2122.             theCollapseElementEvent = (TAppleEvent *)FreeIfObject(theCollapseElementEvent);
  2123.             fi.ReSignal();
  2124.         }
  2125.         
  2126.     return theCollapseElementEvent;
  2127.  
  2128. }
  2129. //----------------------------------------------------------------------------------------
  2130. //    TCollapseElementCommand::DoIt:    
  2131. //----------------------------------------------------------------------------------------
  2132. #pragma segment ADoCommand
  2133. void TCollapseElementCommand::DoIt()
  2134. {
  2135.  
  2136.     fTwistDownDocument -> CollapseElement(fElementToCollapse);
  2137.     //I've got to increment fNumberOfCollapsedControls here 
  2138.     //and decrement fNumberOfExpandedControls here to account for the 
  2139.     //twistDownControl being collapsed. All other controls will take
  2140.     //care of themselves.
  2141.     fTwistDownView -> IncrementNumberOfCollapsedControls();
  2142.     fTwistDownView -> DecrementNumberOfExpandedControls();        
  2143.     fTwistDownView -> SetTheCouldFlags();
  2144.  
  2145. }
  2146. #pragma segment Inline